from __future__ import division
import sys,os,time
from src.Equipments.LockIn import SR830
from src.Equipments.RFGenerator import E8257D
from src.Equipments.multimeter import AgilentMulti
from src.Equipments.gaussmeter import Lakeshore455
from src.Physics.ShallowDonor import Shallow_Donor

from src.Data.DataStructure import Data

import numpy as np
import matplotlib.pyplot as plt

User="PierreAndre"
#import pylab as plb
home_path=os.getcwd()+os.sep#Current path to this program
sys.path.append(home_path+"src"+os.sep)
data_path=home_path+"Users"+os.sep+User+os.sep+"data"+os.sep#For saving later on data
#print data_path

#########################################################
### Parameters - Calibration settings
#########################################################
number_of_points=2*60*2 #Total number of points
#Minimum waiting time = about 300 ms (plot time is limitant)
waiting_time=100	#ms, Waiting time for each point
test=True #If standalone without anything connected->True
#########################################################
#########################################################

#########################################################
### Parameters - Lockin
#########################################################
lockin=SR830("GPIB0::9::INSTR",test)
lockin.Reset_Memory()
lockin.Set_InterExter_Mode(1) #1 for internal mode, 2 for external mode (generated by RF-gen)
lockin.Set_Time_Constant(0.3)
lockin.Set_Harm(2)  #number of harmonics
lockin.Set_Freq(3012) #modulation frequency in Hz
#########################################################
#########################################################

#########################################################
### Parameters - Gaussmeter
#########################################################
gaussmeter=Lakeshore455("GPIB0::12::INSTR",test)
#########################################################
#########################################################

#########################################################
### Parameters - RF setup
#########################################################
RF=E8257D("GPIB0::10::INSTR","FM",test)
RF.Set_Modulation_Output(False,False)	#Modulation On = True, LFOutput On = True
RF.Set_Power(0)	#dBm
RF.Set_Frequency(frequency_start)
RF.Set_Output_ONOFF(True)
#########################################################
#########################################################


#########################################################
# Generic functions
#########################################################
###################
# Printing one scan
###################
def Print_progress(current,total,start=0,pre_sentence='Progress: ',post_sentence=""):
    sentence='\r' + pre_sentence + '{:.3%}'.format((current-start)/(total-start))+post_sentence
    sys.stdout.write(sentence)
    sys.stdout.flush()
    
def Print_complete(sentence):
	sys.stdout.write(sentence)
	sys.stdout.flush()
    
###################
# Scan a given B-field region
###################

def Scan(Scan_init,Scan_final,Scan_resolution,Fixed_parameter,Fixed_parameter_unit="gauss",Scan_unit="MHz"):
	measured_data_n_columns=3	#(field_command, X, Y, opt - measured field)
	if recording_field==True:
		data_n_columns+=1
	measured_data_n_lines=(Scan_final-Scan_init)/Scan_resolution
	
	measured_data=np.zeros([measured_data_n_lines+1, measured_data_n_columns]) #+1 is here to take into account all the points
		
	field_command=Binit
	for i in range(measured_data_n_lines+1):
		
		#Setting the field and wait for stabilization
		magnet.SetMagneticField(field_command, field_unit)
		Print_progress(i,measured_data_n_lines+1,pre_sentence='Scanning: ',post_sentence="")
		if not test:
			time.sleep(waiting_time)
		
		#Readings
		measured_data[i,0]=field_command
		X,Y=lockin.Read_XY()
		measured_data[i,1]=X
		measured_data[i,2]=Y
		if recording_field==True:
			measured_data[i,3]=gaussmeter.Measure_Field()
				
		#Update field
		field_command+=resolution
	
	Print_complete("Scan complete.")
	return measured_data

###################
# Find 0-field
###################

def Find_peak(data):
	
	optimum=np.sqrt(data[0,1]**2+data[0,2]**2)
	optimum_position=0
	
	for i in range(np.size(data[:,0])):
		current_norm=np.sqrt(data[i,1]**2+data[i,2]**2)
		if current_norm<=optimum :
			optimum_position = i
			optimum=current_norm
	optimum_field=data[optimum_position,0]
	return optimum_field,optimum_position,optimum

def Scan_and_Find_peak(B0,deltaB,resolution=1,field_unit="gauss"):
	"""
	B0 is the guessed 0-field. It should be set according to the previous calibration
	deltaB is the range (+- deltaB) to scan
	resolution (gauss) is the step size
	"""
	data_acquired=Scan(B0-deltaB,B0+deltaB,resolution,field_unit)
	peak_abscisse,point_number,peak_value=Find_peak(data_acquired,peak_type)
	return peak_abscisse
	

	

#########################################################
#########################################################